#ifndef __CORE_MATRIX4__
#define __CORE_MATRIX4__

#include "CoreDefine.h"
#include "Vector4.h"
namespace Core
{
	class rtVector3;
	class rtMatrix3;

	class rtMatrix4
	{
	public:
		rtMatrix4(void);
		explicit rtMatrix4(const rtVector4& x, const rtVector4& y, const rtVector4& z, const rtVector4& w);
		explicit rtMatrix4(const float xx, const float xy, const float xz, const float xw,
			const float yx, const float yy, const float yz, const float yw,
			const float zx, const float zy, const float zz, const float zw,
			const float wx, const float wy, const float wz, const float ww);
		explicit rtMatrix4(const rtMatrix3& rotation, const rtVector3& translation);
		explicit rtMatrix4(const float src[4][4]);

		static rtMatrix4 mat4_zero;
		static rtMatrix4 mat4_identity;

		const rtVector4&	    operator [] (int index) const;
		rtVector4&		    operator [] (int index);
		rtMatrix4			operator * (const float a) const;
		rtVector4			operator * (const rtVector4& vec) const;
		rtVector3			operator * (const rtVector3& vec) const;
		rtMatrix4			operator * (const rtMatrix4& a) const;
		rtMatrix4			operator + (const rtMatrix4& a) const;
		rtMatrix4			operator - (const rtMatrix4& a) const;
		rtMatrix4&		    operator *= (const float a);
		rtMatrix4&		    operator *= (const rtMatrix4& a);
		rtMatrix4&		    operator += (const rtMatrix4& a);
		rtMatrix4&		    operator -= (const rtMatrix4& a);

		friend rtMatrix4	    operator * (const float a, const rtMatrix4& mat4);
		friend rtVector4	    operator * (const rtVector4& vec, const rtMatrix4& mat4);
		friend rtVector3	    operator * (const rtVector3& vec, const rtMatrix4& mat4);
		friend rtVector4&	operator *= (rtVector4& vec, const rtMatrix4& mat4);
		friend rtVector3&	operator *= (rtVector3& vec, const rtMatrix4& mat4);

		bool			compare(const rtMatrix4& a) const;
		bool			compare(const rtMatrix4& a, const float epsilon) const;
		bool			operator == (const rtMatrix4& a) const;
		bool			operator != (const rtMatrix4& a) const;

		void			zero(void);
		void			identity(void);
		bool			isIdentity(const float epsilon = MATRIX_EPSILON) const;
		bool			isSymmetric(const float epsilon = MATRIX_EPSILON) const;
		bool			isDiagonal(const float epsilon = MATRIX_EPSILON) const;
		bool			isRotated(void) const;

		void			projectVector(const rtVector4& src, rtVector4& dst) const;
		void			unprojectVector(const rtVector4& src, rtVector4& dst) const;

		float			trace(void) const;
		float			determinant(void) const;
		rtMatrix4		transpose(void) const;
		rtMatrix4&		transposeSelf(void);
		rtMatrix4		inverse(void) const;
		bool			inverseSelf(void);
		rtMatrix4		inverseFast(void) const;
		bool			inverseFastSelf(void);
		rtMatrix4		transposeMultiply(const rtMatrix4& b) const;

		int				getDimension(void) const;

		const float*	toFloatPtr(void) const;
		float*			toFloatPtr(void);

	private:
		rtVector4			m_Mat[4];
	};

}
#endif


